package testcasetool.transformation.presentation;

import java.util.List;

import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;

import proyecto.testcasetool.ActionStep;
import proyecto.testcasetool.Actor;
import proyecto.testcasetool.AlternativeFlow;
import proyecto.testcasetool.Parameter;
import proyecto.testcasetool.Scenario;
import proyecto.testcasetool.Step;
import proyecto.testcasetool.Subject;
import proyecto.testcasetool.UseCase;
import proyecto.testcasetool.UseCaseModel;

public class UseCaseHtmlViewer {

	public static String generateUseCaseHtmlTable(UseCase uc) {
		StringBuffer sb = new StringBuffer();
		sb.append("<table align=\"center\" border=\"1\" cellpadding=\"1\" cellspacing=\"1\" style=\"width:100%\">\n");
		sb.append("	<tbody>\n");
		appendNameRow(uc, sb);
		appendDescriptionRow(uc, sb);
		appendSutRow(uc, sb);
		appendActorsRow(uc, sb);
		appendPreconditionRow(uc, sb);
		appendPostConditionRow(uc, sb);
		appendMainScenarioRows(uc, sb);
		appendAlternativeScenariosRows(uc, sb);
		sb.append("	</tbody>\n");
		sb.append("</table>\n");		
		return sb.toString();
	}

	private static void appendAlternativeScenariosRows(UseCase uc,
			StringBuffer sb) {
		sb.append("		<tr>\n");
		sb.append("			<th colspan=\"2\">Alternative Flows</th>\n");
		sb.append("		</tr>\n");
		sb.append("		<tr>\n");
		sb.append("			<td colspan=\"2\" style=\"padding: 5px;\">\n");
		
		List<AlternativeFlow> alts = uc.getAlternativeFlow();
		for (AlternativeFlow flow : alts) {
			appendFlowNameAndCondition(flow, sb);
			sb.append("			<p><u>Alternative Steps:</u></p>\n");
			appendStepsInfo(sb, flow.getStep());
			sb.append("			<p>&nbsp;</p>\n");
		}
		sb.append("			</td>\n");
		sb.append("		</tr>\n");
	}

	private static void appendFlowNameAndCondition(AlternativeFlow flow,
			StringBuffer sb) {
		sb.append("			<p><strong>");
		sb.append(StringEscapeUtils.escapeHtml4(flow.getName()) + 
				"</strong>&nbsp;(branchCondition: " + StringEscapeUtils.escapeHtml4(flow.getCondition()) + ")");
		if (flow.getDescription() != null) {
			sb.append("\n			<br><i>" + StringEscapeUtils.escapeHtml4(flow.getDescription()) + "</i>");
		}
		sb.append("</p>\n");
	}

	private static void appendMainScenarioRows(UseCase uc, StringBuffer sb) {
		sb.append("		<tr>\n");
		sb.append("			<th colspan=\"2\">Main Flow</th>\n");
		sb.append("		</tr>\n");
		appendMainScenarioDescription(sb, uc.getBasicScenario());
	}

	private static void appendMainScenarioDescription(StringBuffer sb,
			Scenario s) {
		sb.append("		<tr>\n");
		sb.append("			<td colspan=\"2\" style=\"padding: 5px;\">\n");
		sb.append("			<p><strong>");
		sb.append(StringEscapeUtils.escapeHtml4(s.getName()) + "</strong>");
		if (s.getDescription() != null) {
			sb.append("\n			<br><i>" + StringEscapeUtils.escapeHtml4(s.getDescription()) + "</i>\n");
		}
		sb.append("</p>\n");
		appendStepsInfo(sb, s.getStep());
		sb.append("			</td>\n");
		sb.append("		</tr>\n");
	}

	private static void appendStepsInfo(StringBuffer sb, List<Step> steps) {
		for (Step step : steps) {
			sb.append("			<p>"); 
			sb.append(StringEscapeUtils.escapeHtml4(step.getId()) + ") "); 
			sb.append(StringEscapeUtils.escapeHtml4(step.getDescription()));
			if (step instanceof ActionStep) {
				Parameter p = ((ActionStep) step).getParameter();
				if (p != null) {
					sb.append(" <strong>{(" + p.getType() + ": " + StringEscapeUtils.escapeHtml4(p.getName()) + 
							", restriction: " + StringEscapeUtils.escapeHtml4(p.getName()) + " " +
							StringEscapeUtils.escapeHtml4(p.getCondition()) + ", " +
							StringEscapeUtils.escapeHtml4(p.getValidity()) + ")}</strong>");
				}
				
			}
			sb.append("</p>\n");
		}
	}

	private static void appendPostConditionRow(UseCase uc, StringBuffer sb) {
		sb.append("		<tr>\n");
		sb.append("			<th>Postconditions</th>\n");
		sb.append("			<td>" + StringEscapeUtils.escapeHtml4(uc.getPostCondition()) + "</td>\n");
		sb.append("		</tr>\n");
	}

	private static void appendPreconditionRow(UseCase uc, StringBuffer sb) {
		sb.append("		<tr>\n");
		sb.append("			<th>Preconditions</th>\n");
		sb.append("			<td>\n");
		sb.append("			<p>" + StringEscapeUtils.escapeHtml4(uc.getPreCondition()) + "</p>\n");
		sb.append("			</td>\n");
		sb.append("		</tr>\n");
	}

	private static void appendActorsRow(UseCase uc, StringBuffer sb) {
		sb.append("		<tr>\n");
		sb.append("			<th>Actors</th>\n");
		sb.append("			<td>\n");
		sb.append("			<p>" + StringEscapeUtils.escapeHtml4(StringUtils.join(uc.getParticipantActor(),", ")) + "</p>\n");
		sb.append("			</td>\n");
		sb.append("		</tr>\n");
	}

	private static void appendSutRow(UseCase uc, StringBuffer sb) {
		sb.append("		<tr>\n");
		sb.append("			<th>System Under Testing</th>\n");
		sb.append("			<td>" + StringEscapeUtils.escapeHtml4(((Subject) uc.eContainer()).getName()) + "</td>\n");
		sb.append("		</tr>\n");
	}

	private static void appendDescriptionRow(UseCase uc, StringBuffer sb) {
		sb.append("		<tr>\n");
		sb.append("			<th>Description</th>\n");
		sb.append("			<td>" + StringEscapeUtils.escapeHtml4(uc.getDescription()) + "</td>\n");
		sb.append("		</tr>\n");
	}

	private static void appendNameRow(UseCase uc, StringBuffer sb) {
		sb.append("		<tr>\n");
		sb.append("			<th>Name</th>\n");
		sb.append("			<td>" + StringEscapeUtils.escapeHtml4(uc.getName()) + "</td>\n");
		sb.append("		</tr>\n");
	}
}
